
package ogame.utilities.ships;

import java.util.ArrayList;
import java.util.HashMap;
import ogame.utilities.research.Research;

/**
 *
 * @author scchang
 */
public class Ships extends HashMap<ShipType, Integer> {
    
    public double getSlowestSpeed(Research research){
        Double min = Double.MAX_VALUE;
        for(ShipType ship : this.keySet()){
            if(get(ship) != 0){
                if(Ship.enum2Ship(ship).getSpeed(research) < min){
                    min = Ship.enum2Ship(ship).getSpeed(research);
                }
            }
        }
        return min;
    }
    
    public static Ships parseShips(byte[] input){
        if(input.length == 0){
            throw new IllegalArgumentException("Unable to parse ships since "
                    + "input is length 0.");
        }
        Ships ships = new Ships();
        
        int shipTypes = input[0];
        int currentIndex = 1;
        
        for(int i = 0; i < shipTypes; ++i){
            int shipID = input[currentIndex];
            currentIndex++;
            int numContaining = input[currentIndex];
            int shipNum = 0;
            for(int j = 0; j < numContaining; ++j){
                currentIndex++;
                shipNum = (shipNum*256) + input[currentIndex] + 128;
            }
            
            ShipType type = ShipType.values()[shipID];
            
            ships.put(type, shipNum);
            currentIndex++;
        }
        return ships;
    }
    
    public byte[] encode(){
        ArrayList<Byte> theList = new ArrayList<>();
        
        theList.add(Byte.parseByte("" + this.keySet().size()));
        
        for(ShipType type:this.keySet()){
            int shipID = type.ordinal();
            theList.add(Byte.parseByte("" + shipID));
            
            int count = 0;
            int value = this.get(type);
            if(value != 0){
                count = (int)Math.floor(Math.log(value)/Math.log(256))
                        + 1;
            }else{
                count = 1;
            }
            theList.add(Byte.parseByte("" + count));
            for(int j = count - 1; j >= 0; --j){
                int mod = (int)Math.floor(value/(Math.pow(256, j)));
                value -= mod*Math.pow(256, j);
                mod -= 128;
                theList.add(Byte.parseByte("" + mod));
            }
        }
        
        Byte[] resultByte = new Byte[theList.size()];
        resultByte = theList.toArray(resultByte);

        byte[] result = new byte[theList.size()];
        for(int i = 0; i < result.length; ++i){
            result[i] = resultByte[i];
        }
        return result;
    }
    
    public String toString(){
        String output = "";
        for(ShipType ship: this.keySet()){
            output += ship.name() + " : " + this.get(ship) + '\n';
        }
        if(output.equals("")){ output += '\n'; }
        return output;
    }
    
    public static boolean unitTest(){
        
        Ships ships = new Ships();
        
        int i = 0;
        for(ShipType type : ShipType.values()){
            ships.put(type, i);
            ++i;
        }
        
        ships.put(ShipType.BATTLESHIP, 65537);
        
        i = 0;
        
        Ships result = Ships.parseShips(ships.encode());
        for(ShipType type : ShipType.values()){
            if(ShipType.BATTLESHIP == type){
                if(result.get(type) != 65537){
                    System.out.println("With type: " + type + " got: " + result.get(type) +
                            ". Expected: " + 65537);
                    return false;
                }
            }else if(result.get(type) != i){
                System.out.println("With type: " + type + " got: " + result.get(type) +
                        ". Expected: " + i);
                return false;
            }
            ++i;
        }
        
        result = Ships.parseShips(new Ships().encode());
        if(result.keySet().size() != 0){
            System.out.println("Key set should be 0, it is : " + result.keySet().size());
            return false;
        }
        
        return true;
    }
}
